#include <gtest/gtest.h>
#include "../mqserver/mq_host.hpp"

// std::unordered_map<std::string, std::string> empty_map;
using empty_map = std::unordered_map<std::string, std::string>;

class HostTest : public testing::Test
{
public:
    void SetUp() override
    {
        _host = std::make_shared<bitmq::VirtualHost>("host1", "./data/host1/message/", "./data/host1/host1.db");
        // 创建一批交换机
        _host->declareExchange("e1", bitmq::ExchangeType::DIRECT, true, false, empty_map());
        _host->declareExchange("e2", bitmq::ExchangeType::DIRECT, true, false, empty_map());
        _host->declareExchange("e3", bitmq::ExchangeType::DIRECT, true, false, empty_map());
        // 创建一批队列
        _host->declareQueue("q1", true, false, false, empty_map());
        _host->declareQueue("q2", true, false, false, empty_map());
        _host->declareQueue("q3", true, false, false, empty_map());
        // 建立绑定关系
        _host->bind("e1", "q1", "news.music.#");
        _host->bind("e1", "q2", "news.music.#");
        _host->bind("e1", "q3", "news.music.#");

        _host->bind("e2", "q1", "news.music.#");
        _host->bind("e2", "q2", "news.music.#");
        _host->bind("e2", "q3", "news.music.#");

        _host->bind("e3", "q1", "news.music.#");
        _host->bind("e3", "q2", "news.music.#");
        _host->bind("e3", "q3", "news.music.#");
        ;
        // 发布消息
        _host->basicPublish("q1", nullptr, "Hello World-1");
        _host->basicPublish("q1", nullptr, "Hello World-2");
        _host->basicPublish("q1", nullptr, "Hello World-3");

        _host->basicPublish("q2", nullptr, "Hello World-1");
        _host->basicPublish("q2", nullptr, "Hello World-2");
        _host->basicPublish("q2", nullptr, "Hello World-3");

        _host->basicPublish("q3", nullptr, "Hello World-1");
        _host->basicPublish("q3", nullptr, "Hello World-2");
        _host->basicPublish("q3", nullptr, "Hello World-3");
    }

    void TearDown() override
    {
        _host->clear();
    }

public:
    bitmq::VirtualHost::ptr _host;
};

TEST_F(HostTest, init_test)
{
    // 交换机初始化测试
    ASSERT_EQ(_host->existsExchange("e1"), true);
    ASSERT_EQ(_host->existsExchange("e2"), true);
    ASSERT_EQ(_host->existsExchange("e3"), true);
    // 队列初始化测试
    ASSERT_EQ(_host->existsQueue("q1"), true);
    ASSERT_EQ(_host->existsQueue("q2"), true);
    ASSERT_EQ(_host->existsQueue("q2"), true);
    // 绑定初始化测试
    ASSERT_EQ(_host->existsBinding("e1", "q1"), true);
    ASSERT_EQ(_host->existsBinding("e1", "q2"), true);
    ASSERT_EQ(_host->existsBinding("e1", "q3"), true);

    ASSERT_EQ(_host->existsBinding("e2", "q1"), true);
    ASSERT_EQ(_host->existsBinding("e2", "q2"), true);
    ASSERT_EQ(_host->existsBinding("e2", "q3"), true);

    ASSERT_EQ(_host->existsBinding("e3", "q1"), true);
    ASSERT_EQ(_host->existsBinding("e3", "q2"), true);
    ASSERT_EQ(_host->existsBinding("e3", "q3"), true);

    // 消息队列测试
    bitmq::MessagePtr msg1 = _host->basicConsume("q1");
    ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));
    bitmq::MessagePtr msg2 = _host->basicConsume("q1");
    ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));
    bitmq::MessagePtr msg3 = _host->basicConsume("q1");
    ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));

    bitmq::MessagePtr msg4 = _host->basicConsume("q1");
    ASSERT_EQ(msg4.get(), nullptr);
}

// 删除交换机测试
TEST_F(HostTest, remove_exchange)
{
    _host->deleteExchange("e1");

    ASSERT_EQ(_host->existsBinding("e1", "q1"), false);
    ASSERT_EQ(_host->existsBinding("e1", "q2"), false);
    ASSERT_EQ(_host->existsBinding("e1", "q3"), false);
}
// 删除队列测试
TEST_F(HostTest, remove_queue)
{
    _host->deleteQueue("q1");

    ASSERT_EQ(_host->existsBinding("e1", "q1"), false);
    ASSERT_EQ(_host->existsBinding("e2", "q1"), false);
    ASSERT_EQ(_host->existsBinding("e3", "q1"), false);

    bitmq::MessagePtr msg1 = _host->basicConsume("q1");
    ASSERT_EQ(msg1.get(), nullptr);
}
// 确认消息测试
TEST_F(HostTest, ack_queue)
{
    bitmq::MessagePtr msg1 = _host->basicConsume("q1");
    ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));
    _host->basicAck("q1", msg1->payload().properties().id());

    bitmq::MessagePtr msg2 = _host->basicConsume("q1");
    ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));
    _host->basicAck(std::string("q1"), msg2->payload().properties().id());

    bitmq::MessagePtr msg3 = _host->basicConsume("q1");
    ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));
    _host->basicAck(std::string("q1"), msg3->payload().properties().id());
}

int main(int argc, char *argv[])
{
    testing::InitGoogleTest(&argc, argv);
    int ret = RUN_ALL_TESTS();
    return 0;
}